package com.xiaoxin.experience.service.helper;

import com.xiaoxin.experience.util.SystemUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyEvent;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author xiaoxin
 */
@Slf4j
@Component
public class RobotHelper
{
    private Robot robot;

    public RobotHelper()
    {
        if (SystemUtil.isLinux())
        {
            return;
        }
        try
        {
            robot = new Robot();
        }
        catch (Exception e)
        {
            log.error("robot create fail ",e);
        }
    }

    private Point getNowMouseInfo()
    {
        PointerInfo pointerInfo = MouseInfo.getPointerInfo();
        return pointerInfo.getLocation();
    }

    private void clickMouse(int button, int delay)
    {
        robot.mousePress(button);
        robot.delay(50);
        robot.mouseRelease(button);
        robot.delay(delay);
    }

    public void restart()
    {
        try
        {
            Runtime.getRuntime().exec("shutdown -r -t 0");
        }
        catch (Exception ignore) {}
    }

    public void stop()
    {
        try
        {
            Runtime.getRuntime().exec("shutdown -s -f -t 0");
        }
        catch (Exception ignore)
        {}
    }

    public void copy(String text)
    {
        StringSelection stringSelection = new StringSelection(text);
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        clipboard.setContents(stringSelection, stringSelection);
        pressKeyWithShift(KeyEvent.VK_V);
    }

    public void inputEndEnter(String text)
    {
        input(text);
        enter();
    }

    public void input(String text)
    {
        char temp;
        for (int i = 0; i < text.length(); i++)
        {
            temp = text.charAt(i);
            if (temp >= 'A' && temp <= 'Z')
            {
                typeUpperCase(temp);
            }
            else if (temp >= 'a' && temp <= 'z')
            {
                typeLowerCase(temp);
            }
            else if (temp >= '0' && temp <= '9')
            {
                typeNumber(temp);
            }
            else
            {
                typeOther(temp);
            }
        }
    }

    void typeLowerCase(char c)
    {
        robot.keyPress(c - 32);
        robot.keyRelease(c - 32);
        delay();
    }

    void typeUpperCase(char c)
    {
        pressKeyWithShift(c);
    }

    void typeNumber(char c)
    {
        robot.keyPress(c);
        robot.keyRelease(c);
        delay();
    }

    void typeOther(char c)
    {
        switch (c)
        {
            case '+':
                pressKeyWithShift(61);
                break;
            case '-':
                pressKey(45);
                break;
            case '*':
                pressKeyWithShift(56);
                break;
            case '/':
                pressKey(47);
                break;
            case '\'':
                pressKey(222);
                break;
            case ':':
                pressKeyWithShift(59);
                break;
            case '{':
                pressKeyWithShift(91);
                break;
            case '}':
                pressKeyWithShift(93);
                break;
            case '[':
                pressKey(91);
                break;
            case ']':
                pressKey(93);
                break;
            case ';':
                pressKey(59);
                break;
            case '#':
                pressKeyWithShift(51);
                break;
            case '!':
                pressKeyWithShift(49);
                break;
            case '%':
                pressKeyWithShift(53);
                break;
            case '&':
                pressKeyWithShift(55);
                break;
            case '=':
                pressKey(61);
                break;
            case ' ':
                pressKey(32);
                break;
            case '	':
                pressKey(9);
                break;
            case '\n':
                pressKey(10);
                break;
            case '<':
                pressKeyWithShift(44);
                break;
            case '>':
                pressKeyWithShift(46);
                break;
            case '?':
                pressKeyWithShift(47);
                break;
            case '.':
                pressKey(46);
                break;
            case '"':
                pressKeyWithShift(222);
                break;
            case '(':
                pressKeyWithShift(57);
                break;
            case ')':
                pressKeyWithShift(48);
                break;
            case '\\':
                pressKey(92);
                break;
            case ',':
                pressKey(44);
                break;
            case '@':
                pressKeyWithShift(50);
                break;
            case '|':
                pressKeyWithShift(92);
                break;
            case '^':
                pressKeyWithShift(54);
                break;
            case '_':
                pressKeyWithShift(45);
                break;
        }
    }

    private void delay()
    {
        delay(200,TimeUnit.MILLISECONDS);
    }

    public void delaySecond(int seconds)
    {
        delay(seconds,TimeUnit.SECONDS);
    }

    public void delay(int delay, TimeUnit timeUnit)
    {
        robot.delay((int) timeUnit.toMillis(delay));
    }

    public void pressKeyWithShift(int key)
    {
        robot.keyPress(KeyEvent.VK_SHIFT);
        robot.keyPress(key);
        robot.keyRelease(key);
        robot.keyRelease(KeyEvent.VK_SHIFT);
        delay();
    }

    public void pressKeyWithCtrl(int key)
    {
        robot.keyPress(KeyEvent.VK_CONTROL);
        robot.keyPress(key);
        robot.keyPress(key);
        robot.keyRelease(KeyEvent.VK_CONTROL);
        delay();
    }

    public void pressKey(int ... keys)
    {
        if (Objects.nonNull(keys))
        {
            for (int key : keys)
            {
                robot.keyPress(key);
                robot.delay(50);
            }
            for (int i = keys.length - 1; i >= 0; i--)
            {
                robot.keyRelease(keys[i]);
                robot.delay(50);
            }
        }
        delay();
    }

    public void enter()
    {
        robot.keyPress(KeyEvent.VK_ENTER);
        robot.keyRelease(KeyEvent.VK_ENTER);
        delay();
    }
}
